#include "cxispinbox_p.h"
#include <QFocusEvent>
#include <QSignalBlocker>
#include <QToolButton>

CxiSpinBoxPrivate::CxiSpinBoxPrivate(CxiSpinBox* q)
	: q_ptr(q)
{
	init();
}
CxiSpinBoxPrivate::~CxiSpinBoxPrivate() = default;

void CxiSpinBoxPrivate::init()
{
	Q_Q(CxiSpinBox);
	upButton = new QToolButton(q);
	upButton->setText("▲");
	downButton = new QToolButton(q);
	downButton->setText("▼");
	QObject::connect(upButton, &QToolButton::clicked, [this]() {
		if (!isString)
		{
			calculateNextValue(true);
		}
	});

	QObject::connect(downButton, &QToolButton::clicked, [this]() {
		if (!isString)
		{
			calculateNextValue(false);
		}
	});

	QObject::connect(q, &QLineEdit::textChanged, [this, q](const QString& text) {
		value = q->text().isEmpty() ? QVariant(0) : QVariant(text);
	});

	minimum = INT_MIN;
	maximum = INT_MAX;
	updateNumberEditorStyle();
}


void CxiSpinBoxPrivate::layoutButtons()
{
	Q_Q(CxiSpinBox);
	if (!upButton || !downButton)
		return;// 安全退出，避免空指针

	const int buttonWidth = 18;
	const int h = q->height() / 2;
	const int right = q->width() - buttonWidth;
	upButton->setGeometry(right, 0, buttonWidth, h);
	downButton->setGeometry(right, h, buttonWidth, h);
}
void CxiSpinBoxPrivate::calculateNextValue(bool increase)
{
	Q_Q(CxiSpinBox);
	if (isDecimal)
	{
		qreal oldValue = value.toReal();
		qreal newValue = increase ? oldValue + increment : oldValue - increment;
		newValue = std::max(minimum.toReal(), std::min(newValue, maximum.toReal()));

		double roundedValue = std::round(newValue * 1e6) / 1e6;

		// 修复逻辑
		if (!isAllowNegativeNumber && roundedValue < 0)
		{
			roundedValue = 0;
		}
		value = QVariant(roundedValue);
		q->setText(QString::number(roundedValue, 'f', 6));
		emit q->valueChanged(roundedValue);
	}
	else
	{
		int newValue = increase ? value.toInt() + qIntCast(increment)
								: value.toInt() - qIntCast(increment);
		newValue = std::max(minimum.toInt(), std::min(newValue, maximum.toInt()));

		// 修复逻辑
		if (!isAllowNegativeNumber && newValue < 0)
		{
			newValue = 0;
		}

		value = QVariant(newValue);
		q->setText(QString::number(newValue));
		emit q->valueChanged(newValue);
	}

}
void CxiSpinBoxPrivate::onFocusIn(QFocusEvent* event)
{
	Q_Q(CxiSpinBox);
	if (q->text().isEmpty())
		return;

	if (event->gotFocus())
	{
		// 当获得焦点时显示“原始值”，不带格式化
		if (isDecimal)
			q->setText(QString::number(value.toDouble(), 'g', 16));
		else
			q->setText(QString::number(value.toInt()));
	}
}

void CxiSpinBoxPrivate::onFocusOut(QFocusEvent* event)
{
	Q_Q(CxiSpinBox);
	if (q->text().isEmpty())
		return;

	QSignalBlocker blocker(q);
	if (event->lostFocus())
	{
		double val = value.toDouble();
		QString formatted = formatNumber(val);
		q->setText(formatted);
	}
}

QString CxiSpinBoxPrivate::formatNumber(double val) const
{
	QString text;
	QLocale locale;

	switch (formatStyle)
	{
	case CxiSpinBox::Default:
	{
		if (isDecimal)
		{
			// 显示定点小数
			text = QString::number(val, 'f', decimal);
		}
		else
		{
			text = QString::number(static_cast<int>(val));
		}
		break;
	}
	case CxiSpinBox::Currency:
	{
		// 千分位
		text = locale.toString(val, 'f', decimal);
		break;
	}
	case CxiSpinBox::CurrencyWithSign:
	{
		// ￥+千分位
		text = QStringLiteral("￥") + locale.toString(val, 'f', decimal);
		break;
	}
	}
	return text;
}
void CxiSpinBoxPrivate::updateNumberEditorStyle()
{
	Q_Q(CxiSpinBox);

	if (numberEditorStyle == CxiSpinBox::NumericUpDown)
	{
		if (upButton) upButton->show();
		if (downButton) downButton->show();
		layoutButtons();
	}
	else if (numberEditorStyle == CxiSpinBox::Numeric)
	{
		if (upButton) upButton->hide();
		if (downButton) downButton->hide();
	}

	q->update();
}
